#ifndef MINIBASIC_LEXECUTIONER_H
#define MINIBASIC_LEXECUTIONER_H

#pragma once

#include "stdafx.h"
#include <map>
#include <oleauto.h>
#include "../Lexer/FlexLexerProxy.h"
#include "MemoryArea.h"

namespace MiniBasic
{
    struct Vals;
    struct ParseParams;

    class Lexecutioner : public yyFlexLexer
    {
    public:
        typedef std::map<mbint, ULONG_PTR> fileMap;
        typedef fileMap::const_iterator filePosition;

        explicit Lexecutioner(BSTR file);
        Lexecutioner(const char* code, SIZE_T length, bool hasTextLineNumbers);

        bool LineExists(mbint line) const;
        void MoveToLine(mbint line);
        void MoveToFilePosition(ULONG_PTR fileOffset, bool adjustFilePosition = true);
        filePosition GetCurrentLine() const;
        ULONG_PTR GetCurrentFilePosition(bool movePastIfCurrentNewLine = false);
        void GotoNextLine(bool shouldSeek = false);
        bool SeenAssign() const;
        void SeenAssign(bool hasSeenAssign);

        void PutBackLastToken();

        // definition of this is in Lexer.cpp
        int yylex(Vals* yylval, ParseParams* parseParams);
        int yylex();

        // checks that file is a valid minibasic file
        // by checking the signature, ascending line numbers
        // unique line numbers, and line numbers less than MB_MAXLINENO
        static HRESULT CheckFileValidity(BSTR file);

    private:
        // line numbers and bytes offsets to where the line starts in the memory area
        fileMap linesAndOffsets;
        // the current line and position, used when setting up For's and gosub's 
        filePosition linePosition;
        // wheher there's already been an = on this line
        bool seenAssign;
        // representation of the MiniBasic file in memory
        MemoryArea mbFile;

        // copies the minibasic file into the above memory area
        // recording and stripping line numbers as it goes
        HRESULT PrepareFile(BSTR file);

        HRESULT PrepareCode(std::istringstream& codeInMemory, SIZE_T length, bool hasTextLineNumbers);

        // overriding the yyFlexLexers version
        virtual int LexerInput( char* buf, int max_size);
    };
}

#endif
